{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 基于streamlit的大模型应用开发2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#导入语言模型\n",
    "import os\n",
    "from langchain_community.llms import Tongyi\n",
    "from langchain_community.llms import SparkLLM\n",
    "from langchain_community.llms import QianfanLLMEndpoint\n",
    "\n",
    "import pandas as pd\n",
    "#导入模版\n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "#导入聊天模型\n",
    "from langchain.prompts.chat import (\n",
    "    ChatPromptTemplate,\n",
    "    SystemMessagePromptTemplate,\n",
    "    AIMessagePromptTemplate,\n",
    "    HumanMessagePromptTemplate,\n",
    ")\n",
    "from langchain.schema import (\n",
    "    AIMessage,\n",
    "    HumanMessage,\n",
    "    SystemMessage\n",
    ")\n",
    "\n",
    "from langchain_community.chat_models import ChatSparkLLM\n",
    "from langchain_community.chat_models.tongyi import ChatTongyi\n",
    "from langchain_community.chat_models import QianfanChatEndpoint\n",
    "\n",
    "#输入三个模型各自的key\n",
    "\n",
    "os.environ[\"DASHSCOPE_API_KEY\"] = \"\"\n",
    "\n",
    "os.environ[\"IFLYTEK_SPARK_APP_ID\"] = \"\"\n",
    "os.environ[\"IFLYTEK_SPARK_API_KEY\"] = \"\"\n",
    "os.environ[\"IFLYTEK_SPARK_API_SECRET\"] = \"\"\n",
    "\n",
    "os.environ[\"QIANFAN_AK\"] = \"\"\n",
    "os.environ[\"QIANFAN_SK\"] = \"\"\n",
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_ty = Tongyi(temperature=0)\n",
    "model_qf = QianfanLLMEndpoint(model=\"ERNIE-Bot\")\n",
    "chat_qf = QianfanChatEndpoint(model=\"ERNIE-Bot\")\n",
    "chat_xh = ChatSparkLLM()\n",
    "chat_ty= ChatTongyi()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0.1.16'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import langchain\n",
    "langchain.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "#! pip install --upgrade langchain -i https://mirrors.aliyun.com/pypi/simple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 基于streamlit的大模型问答应用实现-通义千问\n",
    "\n",
    "* 原生通义千问问答实现\n",
    "\n",
    "* 基于streamlit回话状态实现记忆功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import dashscope\n",
    "from dashscope import Generation\n",
    "import streamlit as st\n",
    "\n",
    "dashscope.api_key = \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt=[]\n",
    "def get_response(mess):\n",
    "    response = Generation.call(\n",
    "        model='qwen-turbo',\n",
    "        messages=mess,\n",
    "        result_format='message', # 将输出设置为message形式\n",
    "    )\n",
    "    return response\n",
    "\n",
    "def prompt_yun(ct):\n",
    "    prompt.append({\"role\":\"user\",\"content\":ct})\n",
    "    return prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "p_y=prompt_yun(\"你好\")\n",
    "res=get_response(p_y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GenerationResponse(status_code=<HTTPStatus.OK: 200>, request_id='c3470d10-f056-93c6-96e3-92bef9f33053', code='', message='', output=GenerationOutput(text=None, choices=[Choice(finish_reason='stop', message=Message({'role': 'assistant', 'content': '你好！很高兴能为你服务。有什么可以帮助你的吗？'}))], finish_reason=None), usage=GenerationUsage(input_tokens=9, output_tokens=12))"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'role': 'assistant', 'content': '你好！很高兴能为你服务。有什么可以帮助你的吗？'}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict(res.output.choices[0].message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'你好！很高兴能为你服务。有什么可以帮助你的吗？'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res.output.choices[0].message['content']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 参数的输入-langchain-streamlit大模型应用开发\n",
    "\n",
    "* streamlit文档\n",
    "\n",
    "https://docs.streamlit.io/develop/api-reference\n",
    "\n",
    "* st.sidebar.text_input\n",
    "\n",
    "* st.sidebar.select_slider"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on class Tongyi in module langchain_community.llms.tongyi:\n",
      "\n",
      "class Tongyi(langchain_core.language_models.llms.BaseLLM)\n",
      " |  Tongyi(*, name: Optional[str] = None, cache: ForwardRef('Union[BaseCache, bool, None]') = None, verbose: bool = None, callbacks: ForwardRef('Callbacks') = None, tags: Optional[List[str]] = None, metadata: Optional[Dict[str, Any]] = None, custom_get_token_ids: Optional[Callable[[str], List[int]]] = None, callback_manager: Optional[langchain_core.callbacks.base.BaseCallbackManager] = None, client: Any = None, model_name: str = 'qwen-plus', model_kwargs: Dict[str, Any] = None, top_p: float = 0.8, dashscope_api_key: Optional[str] = None, streaming: bool = False, max_retries: int = 10) -> None\n",
      " |  \n",
      " |  Tongyi Qwen large language models.\n",
      " |  \n",
      " |  To use, you should have the ``dashscope`` python package installed, and the\n",
      " |  environment variable ``DASHSCOPE_API_KEY`` set with your API key, or pass\n",
      " |  it as a named parameter to the constructor.\n",
      " |  \n",
      " |  Example:\n",
      " |      .. code-block:: python\n",
      " |  \n",
      " |          from langchain_community.llms import Tongyi\n",
      " |          tongyi = tongyi()\n",
      " |  \n",
      " |  Method resolution order:\n",
      " |      Tongyi\n",
      " |      langchain_core.language_models.llms.BaseLLM\n",
      " |      langchain_core.language_models.base.BaseLanguageModel\n",
      " |      langchain_core.runnables.base.RunnableSerializable\n",
      " |      langchain_core.load.serializable.Serializable\n",
      " |      pydantic.v1.main.BaseModel\n",
      " |      pydantic.v1.utils.Representation\n",
      " |      langchain_core.runnables.base.Runnable\n",
      " |      typing.Generic\n",
      " |      abc.ABC\n",
      " |      builtins.object\n",
      " |  \n",
      " |  Class methods defined here:\n",
      " |  \n",
      " |  validate_environment(values: 'Dict') -> 'Dict' from pydantic.v1.main.ModelMetaclass\n",
      " |      Validate that api key and python package exists in environment.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Static methods defined here:\n",
      " |  \n",
      " |  __json_encoder__ = pydantic_encoder(obj: Any) -> Any\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Readonly properties defined here:\n",
      " |  \n",
      " |  lc_secrets\n",
      " |      A map of constructor argument names to secret ids.\n",
      " |      \n",
      " |      For example,\n",
      " |          {\"openai_api_key\": \"OPENAI_API_KEY\"}\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data and other attributes defined here:\n",
      " |  \n",
      " |  __abstractmethods__ = frozenset()\n",
      " |  \n",
      " |  __annotations__ = {'client': 'Any', 'dashscope_api_key': 'Optional[str...\n",
      " |  \n",
      " |  __class_vars__ = set()\n",
      " |  \n",
      " |  __config__ = <class 'pydantic.v1.config.Config'>\n",
      " |  \n",
      " |  __custom_root_type__ = False\n",
      " |  \n",
      " |  __exclude_fields__ = {'callback_manager': True, 'callbacks': True, 'cu...\n",
      " |  \n",
      " |  __fields__ = {'cache': ModelField(name='cache', type=Union[BaseCache, ...\n",
      " |  \n",
      " |  __hash__ = None\n",
      " |  \n",
      " |  __include_fields__ = None\n",
      " |  \n",
      " |  __parameters__ = ()\n",
      " |  \n",
      " |  __post_root_validators__ = [(False, <function BaseLLM.raise_deprecatio...\n",
      " |  \n",
      " |  __pre_root_validators__ = []\n",
      " |  \n",
      " |  __private_attributes__ = {}\n",
      " |  \n",
      " |  __schema_cache__ = {}\n",
      " |  \n",
      " |  __signature__ = <Signature (*, name: Optional[str] = None, cache...ng:...\n",
      " |  \n",
      " |  __validators__ = {'verbose': [<pydantic.v1.class_validators.Validator ...\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from langchain_core.language_models.llms.BaseLLM:\n",
      " |  \n",
      " |  __call__(self, prompt: 'str', stop: 'Optional[List[str]]' = None, callbacks: 'Callbacks' = None, *, tags: 'Optional[List[str]]' = None, metadata: 'Optional[Dict[str, Any]]' = None, **kwargs: 'Any') -> 'str'\n",
      " |      [*Deprecated*] Check Cache and run the LLM on the given prompt and input.\n",
      " |      \n",
      " |      Notes\n",
      " |      -----\n",
      " |      .. deprecated:: langchain-core==0.1.7\n",
      " |         Use invoke instead.\n",
      " |  \n",
      " |  __str__(self) -> 'str'\n",
      " |      Get a string representation of the object for printing.\n",
      " |  \n",
      " |  async abatch(self, inputs: 'List[LanguageModelInput]', config: 'Optional[Union[RunnableConfig, List[RunnableConfig]]]' = None, *, return_exceptions: 'bool' = False, **kwargs: 'Any') -> 'List[str]'\n",
      " |      Default implementation runs ainvoke in parallel using asyncio.gather.\n",
      " |      \n",
      " |      The default implementation of batch works well for IO bound runnables.\n",
      " |      \n",
      " |      Subclasses should override this method if they can batch more efficiently;\n",
      " |      e.g., if the underlying runnable uses an API which supports a batch mode.\n",
      " |  \n",
      " |  async agenerate(self, prompts: 'List[str]', stop: 'Optional[List[str]]' = None, callbacks: 'Optional[Union[Callbacks, List[Callbacks]]]' = None, *, tags: 'Optional[Union[List[str], List[List[str]]]]' = None, metadata: 'Optional[Union[Dict[str, Any], List[Dict[str, Any]]]]' = None, run_name: 'Optional[Union[str, List[str]]]' = None, run_id: 'Optional[Union[uuid.UUID, List[Optional[uuid.UUID]]]]' = None, **kwargs: 'Any') -> 'LLMResult'\n",
      " |      Asynchronously pass a sequence of prompts to a model and return generations.\n",
      " |      \n",
      " |      This method should make use of batched calls for models that expose a batched\n",
      " |      API.\n",
      " |      \n",
      " |      Use this method when you want to:\n",
      " |          1. take advantage of batched calls,\n",
      " |          2. need more output from the model than just the top generated value,\n",
      " |          3. are building chains that are agnostic to the underlying language model\n",
      " |              type (e.g., pure text completion models vs chat models).\n",
      " |      \n",
      " |      Args:\n",
      " |          prompts: List of string prompts.\n",
      " |          stop: Stop words to use when generating. Model output is cut off at the\n",
      " |              first occurrence of any of these substrings.\n",
      " |          callbacks: Callbacks to pass through. Used for executing additional\n",
      " |              functionality, such as logging or streaming, throughout generation.\n",
      " |          **kwargs: Arbitrary additional keyword arguments. These are usually passed\n",
      " |              to the model provider API call.\n",
      " |      \n",
      " |      Returns:\n",
      " |          An LLMResult, which contains a list of candidate Generations for each input\n",
      " |              prompt and additional model provider-specific output.\n",
      " |  \n",
      " |  async agenerate_prompt(self, prompts: 'List[PromptValue]', stop: 'Optional[List[str]]' = None, callbacks: 'Optional[Union[Callbacks, List[Callbacks]]]' = None, **kwargs: 'Any') -> 'LLMResult'\n",
      " |      Asynchronously pass a sequence of prompts and return model generations.\n",
      " |      \n",
      " |      This method should make use of batched calls for models that expose a batched\n",
      " |      API.\n",
      " |      \n",
      " |      Use this method when you want to:\n",
      " |          1. take advantage of batched calls,\n",
      " |          2. need more output from the model than just the top generated value,\n",
      " |          3. are building chains that are agnostic to the underlying language model\n",
      " |              type (e.g., pure text completion models vs chat models).\n",
      " |      \n",
      " |      Args:\n",
      " |          prompts: List of PromptValues. A PromptValue is an object that can be\n",
      " |              converted to match the format of any language model (string for pure\n",
      " |              text generation models and BaseMessages for chat models).\n",
      " |          stop: Stop words to use when generating. Model output is cut off at the\n",
      " |              first occurrence of any of these substrings.\n",
      " |          callbacks: Callbacks to pass through. Used for executing additional\n",
      " |              functionality, such as logging or streaming, throughout generation.\n",
      " |          **kwargs: Arbitrary additional keyword arguments. These are usually passed\n",
      " |              to the model provider API call.\n",
      " |      \n",
      " |      Returns:\n",
      " |          An LLMResult, which contains a list of candidate Generations for each input\n",
      " |              prompt and additional model provider-specific output.\n",
      " |  \n",
      " |  async ainvoke(self, input: 'LanguageModelInput', config: 'Optional[RunnableConfig]' = None, *, stop: 'Optional[List[str]]' = None, **kwargs: 'Any') -> 'str'\n",
      " |      Default implementation of ainvoke, calls invoke from a thread.\n",
      " |      \n",
      " |      The default implementation allows usage of async code even if\n",
      " |      the runnable did not implement a native async version of invoke.\n",
      " |      \n",
      " |      Subclasses should override this method if they can run asynchronously.\n",
      " |  \n",
      " |  async apredict(self, text: 'str', *, stop: 'Optional[Sequence[str]]' = None, **kwargs: 'Any') -> 'str'\n",
      " |      [*Deprecated*] \n",
      " |      \n",
      " |      Notes\n",
      " |      -----\n",
      " |      .. deprecated:: langchain-core==0.1.7\n",
      " |         Use ainvoke instead.\n",
      " |  \n",
      " |  async apredict_messages(self, messages: 'List[BaseMessage]', *, stop: 'Optional[Sequence[str]]' = None, **kwargs: 'Any') -> 'BaseMessage'\n",
      " |      [*Deprecated*] \n",
      " |      \n",
      " |      Notes\n",
      " |      -----\n",
      " |      .. deprecated:: langchain-core==0.1.7\n",
      " |         Use ainvoke instead.\n",
      " |  \n",
      " |  async astream(self, input: 'LanguageModelInput', config: 'Optional[RunnableConfig]' = None, *, stop: 'Optional[List[str]]' = None, **kwargs: 'Any') -> 'AsyncIterator[str]'\n",
      " |      Default implementation of astream, which calls ainvoke.\n",
      " |      Subclasses should override this method if they support streaming output.\n",
      " |  \n",
      " |  batch(self, inputs: 'List[LanguageModelInput]', config: 'Optional[Union[RunnableConfig, List[RunnableConfig]]]' = None, *, return_exceptions: 'bool' = False, **kwargs: 'Any') -> 'List[str]'\n",
      " |      Default implementation runs invoke in parallel using a thread pool executor.\n",
      " |      \n",
      " |      The default implementation of batch works well for IO bound runnables.\n",
      " |      \n",
      " |      Subclasses should override this method if they can batch more efficiently;\n",
      " |      e.g., if the underlying runnable uses an API which supports a batch mode.\n",
      " |  \n",
      " |  dict(self, **kwargs: 'Any') -> 'Dict'\n",
      " |      Return a dictionary of the LLM.\n",
      " |  \n",
      " |  generate(self, prompts: 'List[str]', stop: 'Optional[List[str]]' = None, callbacks: 'Optional[Union[Callbacks, List[Callbacks]]]' = None, *, tags: 'Optional[Union[List[str], List[List[str]]]]' = None, metadata: 'Optional[Union[Dict[str, Any], List[Dict[str, Any]]]]' = None, run_name: 'Optional[Union[str, List[str]]]' = None, run_id: 'Optional[Union[uuid.UUID, List[Optional[uuid.UUID]]]]' = None, **kwargs: 'Any') -> 'LLMResult'\n",
      " |      Pass a sequence of prompts to a model and return generations.\n",
      " |      \n",
      " |      This method should make use of batched calls for models that expose a batched\n",
      " |      API.\n",
      " |      \n",
      " |      Use this method when you want to:\n",
      " |          1. take advantage of batched calls,\n",
      " |          2. need more output from the model than just the top generated value,\n",
      " |          3. are building chains that are agnostic to the underlying language model\n",
      " |              type (e.g., pure text completion models vs chat models).\n",
      " |      \n",
      " |      Args:\n",
      " |          prompts: List of string prompts.\n",
      " |          stop: Stop words to use when generating. Model output is cut off at the\n",
      " |              first occurrence of any of these substrings.\n",
      " |          callbacks: Callbacks to pass through. Used for executing additional\n",
      " |              functionality, such as logging or streaming, throughout generation.\n",
      " |          **kwargs: Arbitrary additional keyword arguments. These are usually passed\n",
      " |              to the model provider API call.\n",
      " |      \n",
      " |      Returns:\n",
      " |          An LLMResult, which contains a list of candidate Generations for each input\n",
      " |              prompt and additional model provider-specific output.\n",
      " |  \n",
      " |  generate_prompt(self, prompts: 'List[PromptValue]', stop: 'Optional[List[str]]' = None, callbacks: 'Optional[Union[Callbacks, List[Callbacks]]]' = None, **kwargs: 'Any') -> 'LLMResult'\n",
      " |      Pass a sequence of prompts to the model and return model generations.\n",
      " |      \n",
      " |      This method should make use of batched calls for models that expose a batched\n",
      " |      API.\n",
      " |      \n",
      " |      Use this method when you want to:\n",
      " |          1. take advantage of batched calls,\n",
      " |          2. need more output from the model than just the top generated value,\n",
      " |          3. are building chains that are agnostic to the underlying language model\n",
      " |              type (e.g., pure text completion models vs chat models).\n",
      " |      \n",
      " |      Args:\n",
      " |          prompts: List of PromptValues. A PromptValue is an object that can be\n",
      " |              converted to match the format of any language model (string for pure\n",
      " |              text generation models and BaseMessages for chat models).\n",
      " |          stop: Stop words to use when generating. Model output is cut off at the\n",
      " |              first occurrence of any of these substrings.\n",
      " |          callbacks: Callbacks to pass through. Used for executing additional\n",
      " |              functionality, such as logging or streaming, throughout generation.\n",
      " |          **kwargs: Arbitrary additional keyword arguments. These are usually passed\n",
      " |              to the model provider API call.\n",
      " |      \n",
      " |      Returns:\n",
      " |          An LLMResult, which contains a list of candidate Generations for each input\n",
      " |              prompt and additional model provider-specific output.\n",
      " |  \n",
      " |  invoke(self, input: 'LanguageModelInput', config: 'Optional[RunnableConfig]' = None, *, stop: 'Optional[List[str]]' = None, **kwargs: 'Any') -> 'str'\n",
      " |      Transform a single input into an output. Override to implement.\n",
      " |      \n",
      " |      Args:\n",
      " |          input: The input to the runnable.\n",
      " |          config: A config to use when invoking the runnable.\n",
      " |             The config supports standard keys like 'tags', 'metadata' for tracing\n",
      " |             purposes, 'max_concurrency' for controlling how much work to do\n",
      " |             in parallel, and other keys. Please refer to the RunnableConfig\n",
      " |             for more details.\n",
      " |      \n",
      " |      Returns:\n",
      " |          The output of the runnable.\n",
      " |  \n",
      " |  predict(self, text: 'str', *, stop: 'Optional[Sequence[str]]' = None, **kwargs: 'Any') -> 'str'\n",
      " |      [*Deprecated*] \n",
      " |      \n",
      " |      Notes\n",
      " |      -----\n",
      " |      .. deprecated:: langchain-core==0.1.7\n",
      " |         Use invoke instead.\n",
      " |  \n",
      " |  predict_messages(self, messages: 'List[BaseMessage]', *, stop: 'Optional[Sequence[str]]' = None, **kwargs: 'Any') -> 'BaseMessage'\n",
      " |      [*Deprecated*] \n",
      " |      \n",
      " |      Notes\n",
      " |      -----\n",
      " |      .. deprecated:: langchain-core==0.1.7\n",
      " |         Use invoke instead.\n",
      " |  \n",
      " |  save(self, file_path: 'Union[Path, str]') -> 'None'\n",
      " |      Save the LLM.\n",
      " |      \n",
      " |      Args:\n",
      " |          file_path: Path to file to save the LLM to.\n",
      " |      \n",
      " |      Example:\n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          llm.save(file_path=\"path/llm.yaml\")\n",
      " |  \n",
      " |  stream(self, input: 'LanguageModelInput', config: 'Optional[RunnableConfig]' = None, *, stop: 'Optional[List[str]]' = None, **kwargs: 'Any') -> 'Iterator[str]'\n",
      " |      Default implementation of stream, which calls invoke.\n",
      " |      Subclasses should override this method if they support streaming output.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Class methods inherited from langchain_core.language_models.llms.BaseLLM:\n",
      " |  \n",
      " |  raise_deprecation(values: 'Dict') -> 'Dict' from pydantic.v1.main.ModelMetaclass\n",
      " |      Raise deprecation warning if callback_manager is used.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Readonly properties inherited from langchain_core.language_models.llms.BaseLLM:\n",
      " |  \n",
      " |  OutputType\n",
      " |      Get the input type for this runnable.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data and other attributes inherited from langchain_core.language_models.llms.BaseLLM:\n",
      " |  \n",
      " |  Config = <class 'langchain_core.language_models.llms.BaseLLM.Config'>\n",
      " |      Configuration for this pydantic object.\n",
      " |  \n",
      " |  \n",
      " |  __orig_bases__ = (langchain_core.language_models.base.BaseLanguageMode...\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from langchain_core.language_models.base.BaseLanguageModel:\n",
      " |  \n",
      " |  get_num_tokens(self, text: 'str') -> 'int'\n",
      " |      Get the number of tokens present in the text.\n",
      " |      \n",
      " |      Useful for checking if an input will fit in a model's context window.\n",
      " |      \n",
      " |      Args:\n",
      " |          text: The string input to tokenize.\n",
      " |      \n",
      " |      Returns:\n",
      " |          The integer number of tokens in the text.\n",
      " |  \n",
      " |  get_num_tokens_from_messages(self, messages: 'List[BaseMessage]') -> 'int'\n",
      " |      Get the number of tokens in the messages.\n",
      " |      \n",
      " |      Useful for checking if an input will fit in a model's context window.\n",
      " |      \n",
      " |      Args:\n",
      " |          messages: The message inputs to tokenize.\n",
      " |      \n",
      " |      Returns:\n",
      " |          The sum of the number of tokens across the messages.\n",
      " |  \n",
      " |  get_token_ids(self, text: 'str') -> 'List[int]'\n",
      " |      Return the ordered ids of the tokens in a text.\n",
      " |      \n",
      " |      Args:\n",
      " |          text: The string input to tokenize.\n",
      " |      \n",
      " |      Returns:\n",
      " |          A list of ids corresponding to the tokens in the text, in order they occur\n",
      " |              in the text.\n",
      " |  \n",
      " |  with_structured_output(self, schema: 'Union[Dict, Type[BaseModel]]', **kwargs: 'Any') -> 'Runnable[LanguageModelInput, Union[Dict, BaseModel]]'\n",
      " |      Implement this if there is a way of steering the model to generate responses that match a given schema.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Class methods inherited from langchain_core.language_models.base.BaseLanguageModel:\n",
      " |  \n",
      " |  set_verbose(verbose: 'Optional[bool]') -> 'bool' from pydantic.v1.main.ModelMetaclass\n",
      " |      If verbose is None, set it.\n",
      " |      \n",
      " |      This allows users to pass in None as verbose to access the global setting.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Readonly properties inherited from langchain_core.language_models.base.BaseLanguageModel:\n",
      " |  \n",
      " |  InputType\n",
      " |      Get the input type for this runnable.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from langchain_core.runnables.base.RunnableSerializable:\n",
      " |  \n",
      " |  configurable_alternatives(self, which: 'ConfigurableField', *, default_key: 'str' = 'default', prefix_keys: 'bool' = False, **kwargs: 'Union[Runnable[Input, Output], Callable[[], Runnable[Input, Output]]]') -> 'RunnableSerializable[Input, Output]'\n",
      " |      Configure alternatives for runnables that can be set at runtime.\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          from langchain_anthropic import ChatAnthropic\n",
      " |          from langchain_core.runnables.utils import ConfigurableField\n",
      " |          from langchain_openai import ChatOpenAI\n",
      " |      \n",
      " |          model = ChatAnthropic(\n",
      " |              model_name=\"claude-3-sonnet-20240229\"\n",
      " |          ).configurable_alternatives(\n",
      " |              ConfigurableField(id=\"llm\"),\n",
      " |              default_key=\"anthropic\",\n",
      " |              openai=ChatOpenAI()\n",
      " |          )\n",
      " |      \n",
      " |          # uses the default model ChatAnthropic\n",
      " |          print(model.invoke(\"which organization created you?\").content)\n",
      " |      \n",
      " |          # uses ChatOpenaAI\n",
      " |          print(\n",
      " |              model.with_config(\n",
      " |                  configurable={\"llm\": \"openai\"}\n",
      " |              ).invoke(\"which organization created you?\").content\n",
      " |          )\n",
      " |  \n",
      " |  configurable_fields(self, **kwargs: 'AnyConfigurableField') -> 'RunnableSerializable[Input, Output]'\n",
      " |      Configure particular runnable fields at runtime.\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          from langchain_core.runnables import ConfigurableField\n",
      " |          from langchain_openai import ChatOpenAI\n",
      " |      \n",
      " |          model = ChatOpenAI(max_tokens=20).configurable_fields(\n",
      " |              max_tokens=ConfigurableField(\n",
      " |                  id=\"output_token_number\",\n",
      " |                  name=\"Max tokens in the output\",\n",
      " |                  description=\"The maximum number of tokens in the output\",\n",
      " |              )\n",
      " |          )\n",
      " |      \n",
      " |          # max_tokens = 20\n",
      " |          print(\n",
      " |              \"max_tokens_20: \",\n",
      " |              model.invoke(\"tell me something about chess\").content\n",
      " |          )\n",
      " |      \n",
      " |          # max_tokens = 200\n",
      " |          print(\"max_tokens_200: \", model.with_config(\n",
      " |              configurable={\"output_token_number\": 200}\n",
      " |              ).invoke(\"tell me something about chess\").content\n",
      " |          )\n",
      " |  \n",
      " |  to_json(self) -> 'Union[SerializedConstructor, SerializedNotImplemented]'\n",
      " |      Serialize the runnable to JSON.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from langchain_core.runnables.base.RunnableSerializable:\n",
      " |  \n",
      " |  __weakref__\n",
      " |      list of weak references to the object (if defined)\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from langchain_core.load.serializable.Serializable:\n",
      " |  \n",
      " |  __repr_args__(self) -> Any\n",
      " |      Returns the attributes to show in __str__, __repr__, and __pretty__ this is generally overridden.\n",
      " |      \n",
      " |      Can either return:\n",
      " |      * name - value pairs, e.g.: `[('foo_name', 'foo'), ('bar_name', ['b', 'a', 'r'])]`\n",
      " |      * or, just values, e.g.: `[(None, 'foo'), (None, ['b', 'a', 'r'])]`\n",
      " |  \n",
      " |  to_json_not_implemented(self) -> langchain_core.load.serializable.SerializedNotImplemented\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Class methods inherited from langchain_core.load.serializable.Serializable:\n",
      " |  \n",
      " |  get_lc_namespace() -> List[str] from pydantic.v1.main.ModelMetaclass\n",
      " |      Get the namespace of the langchain object.\n",
      " |      \n",
      " |      For example, if the class is `langchain.llms.openai.OpenAI`, then the\n",
      " |      namespace is [\"langchain\", \"llms\", \"openai\"]\n",
      " |  \n",
      " |  is_lc_serializable() -> bool from pydantic.v1.main.ModelMetaclass\n",
      " |      Is this class serializable?\n",
      " |  \n",
      " |  lc_id() -> List[str] from pydantic.v1.main.ModelMetaclass\n",
      " |      A unique identifier for this class for serialization purposes.\n",
      " |      \n",
      " |      The unique identifier is a list of strings that describes the path\n",
      " |      to the object.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Readonly properties inherited from langchain_core.load.serializable.Serializable:\n",
      " |  \n",
      " |  lc_attributes\n",
      " |      List of attribute names that should be included in the serialized kwargs.\n",
      " |      \n",
      " |      These attributes must be accepted by the constructor.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from pydantic.v1.main.BaseModel:\n",
      " |  \n",
      " |  __eq__(self, other: Any) -> bool\n",
      " |      Return self==value.\n",
      " |  \n",
      " |  __getstate__(self) -> 'DictAny'\n",
      " |  \n",
      " |  __init__(__pydantic_self__, **data: Any) -> None\n",
      " |      Create a new model by parsing and validating input data from keyword arguments.\n",
      " |      \n",
      " |      Raises ValidationError if the input data cannot be parsed to form a valid model.\n",
      " |  \n",
      " |  __iter__(self) -> 'TupleGenerator'\n",
      " |      so `dict(model)` works\n",
      " |  \n",
      " |  __setattr__(self, name, value)\n",
      " |      Implement setattr(self, name, value).\n",
      " |  \n",
      " |  __setstate__(self, state: 'DictAny') -> None\n",
      " |  \n",
      " |  copy(self: 'Model', *, include: Union[ForwardRef('AbstractSetIntStr'), ForwardRef('MappingIntStrAny'), NoneType] = None, exclude: Union[ForwardRef('AbstractSetIntStr'), ForwardRef('MappingIntStrAny'), NoneType] = None, update: Optional[ForwardRef('DictStrAny')] = None, deep: bool = False) -> 'Model'\n",
      " |      Duplicate a model, optionally choose which fields to include, exclude and change.\n",
      " |      \n",
      " |      :param include: fields to include in new model\n",
      " |      :param exclude: fields to exclude from new model, as with values this takes precedence over include\n",
      " |      :param update: values to change/add in the new model. Note: the data is not validated before creating\n",
      " |          the new model: you should trust this data\n",
      " |      :param deep: set to `True` to make a deep copy of the model\n",
      " |      :return: new model instance\n",
      " |  \n",
      " |  json(self, *, include: Union[ForwardRef('AbstractSetIntStr'), ForwardRef('MappingIntStrAny'), NoneType] = None, exclude: Union[ForwardRef('AbstractSetIntStr'), ForwardRef('MappingIntStrAny'), NoneType] = None, by_alias: bool = False, skip_defaults: Optional[bool] = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, encoder: Optional[Callable[[Any], Any]] = None, models_as_dict: bool = True, **dumps_kwargs: Any) -> str\n",
      " |      Generate a JSON representation of the model, `include` and `exclude` arguments as per `dict()`.\n",
      " |      \n",
      " |      `encoder` is an optional function to supply as `default` to json.dumps(), other arguments as per `json.dumps()`.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Class methods inherited from pydantic.v1.main.BaseModel:\n",
      " |  \n",
      " |  __get_validators__() -> 'CallableGenerator' from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  __try_update_forward_refs__(**localns: Any) -> None from pydantic.v1.main.ModelMetaclass\n",
      " |      Same as update_forward_refs but will not raise exception\n",
      " |      when forward references are not defined.\n",
      " |  \n",
      " |  construct(_fields_set: Optional[ForwardRef('SetStr')] = None, **values: Any) -> 'Model' from pydantic.v1.main.ModelMetaclass\n",
      " |      Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data.\n",
      " |      Default values are respected, but no other validation is performed.\n",
      " |      Behaves as if `Config.extra = 'allow'` was set since it adds all passed values\n",
      " |  \n",
      " |  from_orm(obj: Any) -> 'Model' from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  parse_file(path: Union[str, pathlib.Path], *, content_type: str = None, encoding: str = 'utf8', proto: pydantic.v1.parse.Protocol = None, allow_pickle: bool = False) -> 'Model' from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  parse_obj(obj: Any) -> 'Model' from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  parse_raw(b: Union[str, bytes], *, content_type: str = None, encoding: str = 'utf8', proto: pydantic.v1.parse.Protocol = None, allow_pickle: bool = False) -> 'Model' from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  schema(by_alias: bool = True, ref_template: str = '#/definitions/{model}') -> 'DictStrAny' from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  schema_json(*, by_alias: bool = True, ref_template: str = '#/definitions/{model}', **dumps_kwargs: Any) -> str from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  update_forward_refs(**localns: Any) -> None from pydantic.v1.main.ModelMetaclass\n",
      " |      Try to update ForwardRefs on fields based on this Model, globalns and localns.\n",
      " |  \n",
      " |  validate(value: Any) -> 'Model' from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from pydantic.v1.main.BaseModel:\n",
      " |  \n",
      " |  __dict__\n",
      " |      dictionary for instance variables (if defined)\n",
      " |  \n",
      " |  __fields_set__\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from pydantic.v1.utils.Representation:\n",
      " |  \n",
      " |  __pretty__(self, fmt: Callable[[Any], Any], **kwargs: Any) -> Generator[Any, NoneType, NoneType]\n",
      " |      Used by devtools (https://python-devtools.helpmanual.io/) to provide a human readable representations of objects\n",
      " |  \n",
      " |  __repr__(self) -> str\n",
      " |      Return repr(self).\n",
      " |  \n",
      " |  __repr_name__(self) -> str\n",
      " |      Name of the instance's class, used in __repr__.\n",
      " |  \n",
      " |  __repr_str__(self, join_str: str) -> str\n",
      " |  \n",
      " |  __rich_repr__(self) -> 'RichReprResult'\n",
      " |      Get fields for Rich library\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from langchain_core.runnables.base.Runnable:\n",
      " |  \n",
      " |  __or__(self, other: 'Union[Runnable[Any, Other], Callable[[Any], Other], Callable[[Iterator[Any]], Iterator[Other]], Mapping[str, Union[Runnable[Any, Other], Callable[[Any], Other], Any]]]') -> 'RunnableSerializable[Input, Other]'\n",
      " |      Compose this runnable with another object to create a RunnableSequence.\n",
      " |  \n",
      " |  __ror__(self, other: 'Union[Runnable[Other, Any], Callable[[Other], Any], Callable[[Iterator[Other]], Iterator[Any]], Mapping[str, Union[Runnable[Other, Any], Callable[[Other], Any], Any]]]') -> 'RunnableSerializable[Other, Output]'\n",
      " |      Compose this runnable with another object to create a RunnableSequence.\n",
      " |  \n",
      " |  async abatch_as_completed(self, inputs: 'List[Input]', config: 'Optional[Union[RunnableConfig, List[RunnableConfig]]]' = None, *, return_exceptions: 'bool' = False, **kwargs: 'Optional[Any]') -> 'AsyncIterator[Tuple[int, Union[Output, Exception]]]'\n",
      " |      Run ainvoke in parallel on a list of inputs,\n",
      " |      yielding results as they complete.\n",
      " |  \n",
      " |  assign(self, **kwargs: 'Union[Runnable[Dict[str, Any], Any], Callable[[Dict[str, Any]], Any], Mapping[str, Union[Runnable[Dict[str, Any], Any], Callable[[Dict[str, Any]], Any]]]]') -> 'RunnableSerializable[Any, Any]'\n",
      " |      Assigns new fields to the dict output of this runnable.\n",
      " |      Returns a new runnable.\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          from langchain_community.llms.fake import FakeStreamingListLLM\n",
      " |          from langchain_core.output_parsers import StrOutputParser\n",
      " |          from langchain_core.prompts import SystemMessagePromptTemplate\n",
      " |          from langchain_core.runnables import Runnable\n",
      " |          from operator import itemgetter\n",
      " |      \n",
      " |          prompt = (\n",
      " |              SystemMessagePromptTemplate.from_template(\"You are a nice assistant.\")\n",
      " |              + \"{question}\"\n",
      " |          )\n",
      " |          llm = FakeStreamingListLLM(responses=[\"foo-lish\"])\n",
      " |      \n",
      " |          chain: Runnable = prompt | llm | {\"str\": StrOutputParser()}\n",
      " |      \n",
      " |          chain_with_assign = chain.assign(hello=itemgetter(\"str\") | llm)\n",
      " |      \n",
      " |          print(chain_with_assign.input_schema.schema())\n",
      " |          # {'title': 'PromptInput', 'type': 'object', 'properties':\n",
      " |          {'question': {'title': 'Question', 'type': 'string'}}}\n",
      " |          print(chain_with_assign.output_schema.schema()) #\n",
      " |          {'title': 'RunnableSequenceOutput', 'type': 'object', 'properties':\n",
      " |          {'str': {'title': 'Str',\n",
      " |          'type': 'string'}, 'hello': {'title': 'Hello', 'type': 'string'}}}\n",
      " |  \n",
      " |  astream_events(self, input: 'Any', config: 'Optional[RunnableConfig]' = None, *, version: \"Literal['v1']\", include_names: 'Optional[Sequence[str]]' = None, include_types: 'Optional[Sequence[str]]' = None, include_tags: 'Optional[Sequence[str]]' = None, exclude_names: 'Optional[Sequence[str]]' = None, exclude_types: 'Optional[Sequence[str]]' = None, exclude_tags: 'Optional[Sequence[str]]' = None, **kwargs: 'Any') -> 'AsyncIterator[StreamEvent]'\n",
      " |      [*Beta*] Generate a stream of events.\n",
      " |      \n",
      " |      Use to create an iterator over StreamEvents that provide real-time information\n",
      " |      about the progress of the runnable, including StreamEvents from intermediate\n",
      " |      results.\n",
      " |      \n",
      " |      A StreamEvent is a dictionary with the following schema:\n",
      " |      \n",
      " |      - ``event``: **str** - Event names are of the\n",
      " |          format: on_[runnable_type]_(start|stream|end).\n",
      " |      - ``name``: **str** - The name of the runnable that generated the event.\n",
      " |      - ``run_id``: **str** - randomly generated ID associated with the given execution of\n",
      " |          the runnable that emitted the event.\n",
      " |          A child runnable that gets invoked as part of the execution of a\n",
      " |          parent runnable is assigned its own unique ID.\n",
      " |      - ``tags``: **Optional[List[str]]** - The tags of the runnable that generated\n",
      " |          the event.\n",
      " |      - ``metadata``: **Optional[Dict[str, Any]]** - The metadata of the runnable\n",
      " |          that generated the event.\n",
      " |      - ``data``: **Dict[str, Any]**\n",
      " |      \n",
      " |      \n",
      " |      Below is a table that illustrates some evens that might be emitted by various\n",
      " |      chains. Metadata fields have been omitted from the table for brevity.\n",
      " |      Chain definitions have been included after the table.\n",
      " |      \n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | event                | name             | chunk                           | input                                         | output                                          |\n",
      " |      +======================+==================+=================================+===============================================+=================================================+\n",
      " |      | on_chat_model_start  | [model name]     |                                 | {\"messages\": [[SystemMessage, HumanMessage]]} |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_chat_model_stream | [model name]     | AIMessageChunk(content=\"hello\") |                                               |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_chat_model_end    | [model name]     |                                 | {\"messages\": [[SystemMessage, HumanMessage]]} | {\"generations\": [...], \"llm_output\": None, ...} |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_llm_start         | [model name]     |                                 | {'input': 'hello'}                            |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_llm_stream        | [model name]     | 'Hello'                         |                                               |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_llm_end           | [model name]     |                                 | 'Hello human!'                                |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_chain_start       | format_docs      |                                 |                                               |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_chain_stream      | format_docs      | \"hello world!, goodbye world!\"  |                                               |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_chain_end         | format_docs      |                                 | [Document(...)]                               | \"hello world!, goodbye world!\"                  |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_tool_start        | some_tool        |                                 | {\"x\": 1, \"y\": \"2\"}                            |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_tool_stream       | some_tool        | {\"x\": 1, \"y\": \"2\"}              |                                               |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_tool_end          | some_tool        |                                 |                                               | {\"x\": 1, \"y\": \"2\"}                              |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_retriever_start   | [retriever name] |                                 | {\"query\": \"hello\"}                            |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_retriever_chunk   | [retriever name] | {documents: [...]}              |                                               |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_retriever_end     | [retriever name] |                                 | {\"query\": \"hello\"}                            | {documents: [...]}                              |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_prompt_start      | [template_name]  |                                 | {\"question\": \"hello\"}                         |                                                 |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      | on_prompt_end        | [template_name]  |                                 | {\"question\": \"hello\"}                         | ChatPromptValue(messages: [SystemMessage, ...]) |\n",
      " |      +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+\n",
      " |      \n",
      " |      Here are declarations associated with the events shown above:\n",
      " |      \n",
      " |      `format_docs`:\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          def format_docs(docs: List[Document]) -> str:\n",
      " |              '''Format the docs.'''\n",
      " |              return \", \".join([doc.page_content for doc in docs])\n",
      " |      \n",
      " |          format_docs = RunnableLambda(format_docs)\n",
      " |      \n",
      " |      `some_tool`:\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          @tool\n",
      " |          def some_tool(x: int, y: str) -> dict:\n",
      " |              '''Some_tool.'''\n",
      " |              return {\"x\": x, \"y\": y}\n",
      " |      \n",
      " |      `prompt`:\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          template = ChatPromptTemplate.from_messages(\n",
      " |              [(\"system\", \"You are Cat Agent 007\"), (\"human\", \"{question}\")]\n",
      " |          ).with_config({\"run_name\": \"my_template\", \"tags\": [\"my_template\"]})\n",
      " |      \n",
      " |      \n",
      " |      Example:\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          from langchain_core.runnables import RunnableLambda\n",
      " |      \n",
      " |          async def reverse(s: str) -> str:\n",
      " |              return s[::-1]\n",
      " |      \n",
      " |          chain = RunnableLambda(func=reverse)\n",
      " |      \n",
      " |          events = [\n",
      " |              event async for event in chain.astream_events(\"hello\", version=\"v1\")\n",
      " |          ]\n",
      " |      \n",
      " |          # will produce the following events (run_id has been omitted for brevity):\n",
      " |          [\n",
      " |              {\n",
      " |                  \"data\": {\"input\": \"hello\"},\n",
      " |                  \"event\": \"on_chain_start\",\n",
      " |                  \"metadata\": {},\n",
      " |                  \"name\": \"reverse\",\n",
      " |                  \"tags\": [],\n",
      " |              },\n",
      " |              {\n",
      " |                  \"data\": {\"chunk\": \"olleh\"},\n",
      " |                  \"event\": \"on_chain_stream\",\n",
      " |                  \"metadata\": {},\n",
      " |                  \"name\": \"reverse\",\n",
      " |                  \"tags\": [],\n",
      " |              },\n",
      " |              {\n",
      " |                  \"data\": {\"output\": \"olleh\"},\n",
      " |                  \"event\": \"on_chain_end\",\n",
      " |                  \"metadata\": {},\n",
      " |                  \"name\": \"reverse\",\n",
      " |                  \"tags\": [],\n",
      " |              },\n",
      " |          ]\n",
      " |      \n",
      " |      Args:\n",
      " |          input: The input to the runnable.\n",
      " |          config: The config to use for the runnable.\n",
      " |          version: The version of the schema to use.\n",
      " |                   Currently only version 1 is available.\n",
      " |                   No default will be assigned until the API is stabilized.\n",
      " |          include_names: Only include events from runnables with matching names.\n",
      " |          include_types: Only include events from runnables with matching types.\n",
      " |          include_tags: Only include events from runnables with matching tags.\n",
      " |          exclude_names: Exclude events from runnables with matching names.\n",
      " |          exclude_types: Exclude events from runnables with matching types.\n",
      " |          exclude_tags: Exclude events from runnables with matching tags.\n",
      " |          kwargs: Additional keyword arguments to pass to the runnable.\n",
      " |              These will be passed to astream_log as this implementation\n",
      " |              of astream_events is built on top of astream_log.\n",
      " |      \n",
      " |      Returns:\n",
      " |          An async stream of StreamEvents.\n",
      " |      \n",
      " |      Notes\n",
      " |      -----\n",
      " |      .. beta::\n",
      " |         This API is in beta and may change in the future.\n",
      " |  \n",
      " |  async astream_log(self, input: 'Any', config: 'Optional[RunnableConfig]' = None, *, diff: 'bool' = True, with_streamed_output_list: 'bool' = True, include_names: 'Optional[Sequence[str]]' = None, include_types: 'Optional[Sequence[str]]' = None, include_tags: 'Optional[Sequence[str]]' = None, exclude_names: 'Optional[Sequence[str]]' = None, exclude_types: 'Optional[Sequence[str]]' = None, exclude_tags: 'Optional[Sequence[str]]' = None, **kwargs: 'Any') -> 'Union[AsyncIterator[RunLogPatch], AsyncIterator[RunLog]]'\n",
      " |      Stream all output from a runnable, as reported to the callback system.\n",
      " |      This includes all inner runs of LLMs, Retrievers, Tools, etc.\n",
      " |      \n",
      " |      Output is streamed as Log objects, which include a list of\n",
      " |      jsonpatch ops that describe how the state of the run has changed in each\n",
      " |      step, and the final state of the run.\n",
      " |      \n",
      " |      The jsonpatch ops can be applied in order to construct state.\n",
      " |      \n",
      " |      Args:\n",
      " |          input: The input to the runnable.\n",
      " |          config: The config to use for the runnable.\n",
      " |          diff: Whether to yield diffs between each step, or the current state.\n",
      " |          with_streamed_output_list: Whether to yield the streamed_output list.\n",
      " |          include_names: Only include logs with these names.\n",
      " |          include_types: Only include logs with these types.\n",
      " |          include_tags: Only include logs with these tags.\n",
      " |          exclude_names: Exclude logs with these names.\n",
      " |          exclude_types: Exclude logs with these types.\n",
      " |          exclude_tags: Exclude logs with these tags.\n",
      " |  \n",
      " |  async atransform(self, input: 'AsyncIterator[Input]', config: 'Optional[RunnableConfig]' = None, **kwargs: 'Optional[Any]') -> 'AsyncIterator[Output]'\n",
      " |      Default implementation of atransform, which buffers input and calls astream.\n",
      " |      Subclasses should override this method if they can start producing output while\n",
      " |      input is still being generated.\n",
      " |  \n",
      " |  batch_as_completed(self, inputs: 'List[Input]', config: 'Optional[Union[RunnableConfig, List[RunnableConfig]]]' = None, *, return_exceptions: 'bool' = False, **kwargs: 'Optional[Any]') -> 'Iterator[Tuple[int, Union[Output, Exception]]]'\n",
      " |      Run invoke in parallel on a list of inputs,\n",
      " |      yielding results as they complete.\n",
      " |  \n",
      " |  bind(self, **kwargs: 'Any') -> 'Runnable[Input, Output]'\n",
      " |      Bind arguments to a Runnable, returning a new Runnable.\n",
      " |      \n",
      " |      Useful when a runnable in a chain requires an argument that is not\n",
      " |      in the output of the previous runnable or included in the user input.\n",
      " |      \n",
      " |      Example:\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |      \n",
      " |          from langchain_community.chat_models import ChatOllama\n",
      " |          from langchain_core.output_parsers import StrOutputParser\n",
      " |      \n",
      " |          llm = ChatOllama(model='llama2')\n",
      " |      \n",
      " |          # Without bind.\n",
      " |          chain = (\n",
      " |              llm\n",
      " |              | StrOutputParser()\n",
      " |          )\n",
      " |      \n",
      " |          chain.invoke(\"Repeat quoted words exactly: 'One two three four five.'\")\n",
      " |          # Output is 'One two three four five.'\n",
      " |      \n",
      " |          # With bind.\n",
      " |          chain = (\n",
      " |              llm.bind(stop=[\"three\"])\n",
      " |              | StrOutputParser()\n",
      " |          )\n",
      " |      \n",
      " |          chain.invoke(\"Repeat quoted words exactly: 'One two three four five.'\")\n",
      " |          # Output is 'One two'\n",
      " |  \n",
      " |  config_schema(self, *, include: 'Optional[Sequence[str]]' = None) -> 'Type[BaseModel]'\n",
      " |      The type of config this runnable accepts specified as a pydantic model.\n",
      " |      \n",
      " |      To mark a field as configurable, see the `configurable_fields`\n",
      " |      and `configurable_alternatives` methods.\n",
      " |      \n",
      " |      Args:\n",
      " |          include: A list of fields to include in the config schema.\n",
      " |      \n",
      " |      Returns:\n",
      " |          A pydantic model that can be used to validate config.\n",
      " |  \n",
      " |  get_graph(self, config: 'Optional[RunnableConfig]' = None) -> 'Graph'\n",
      " |      Return a graph representation of this runnable.\n",
      " |  \n",
      " |  get_input_schema(self, config: 'Optional[RunnableConfig]' = None) -> 'Type[BaseModel]'\n",
      " |      Get a pydantic model that can be used to validate input to the runnable.\n",
      " |      \n",
      " |      Runnables that leverage the configurable_fields and configurable_alternatives\n",
      " |      methods will have a dynamic input schema that depends on which\n",
      " |      configuration the runnable is invoked with.\n",
      " |      \n",
      " |      This method allows to get an input schema for a specific configuration.\n",
      " |      \n",
      " |      Args:\n",
      " |          config: A config to use when generating the schema.\n",
      " |      \n",
      " |      Returns:\n",
      " |          A pydantic model that can be used to validate input.\n",
      " |  \n",
      " |  get_name(self, suffix: 'Optional[str]' = None, *, name: 'Optional[str]' = None) -> 'str'\n",
      " |      Get the name of the runnable.\n",
      " |  \n",
      " |  get_output_schema(self, config: 'Optional[RunnableConfig]' = None) -> 'Type[BaseModel]'\n",
      " |      Get a pydantic model that can be used to validate output to the runnable.\n",
      " |      \n",
      " |      Runnables that leverage the configurable_fields and configurable_alternatives\n",
      " |      methods will have a dynamic output schema that depends on which\n",
      " |      configuration the runnable is invoked with.\n",
      " |      \n",
      " |      This method allows to get an output schema for a specific configuration.\n",
      " |      \n",
      " |      Args:\n",
      " |          config: A config to use when generating the schema.\n",
      " |      \n",
      " |      Returns:\n",
      " |          A pydantic model that can be used to validate output.\n",
      " |  \n",
      " |  get_prompts(self, config: 'Optional[RunnableConfig]' = None) -> 'List[BasePromptTemplate]'\n",
      " |  \n",
      " |  map(self) -> 'Runnable[List[Input], List[Output]]'\n",
      " |      Return a new Runnable that maps a list of inputs to a list of outputs,\n",
      " |      by calling invoke() with each input.\n",
      " |      \n",
      " |      Example:\n",
      " |      \n",
      " |          .. code-block:: python\n",
      " |      \n",
      " |                  from langchain_core.runnables import RunnableLambda\n",
      " |      \n",
      " |                  def _lambda(x: int) -> int:\n",
      " |                      return x + 1\n",
      " |      \n",
      " |                  runnable = RunnableLambda(_lambda)\n",
      " |                  print(runnable.map().invoke([1, 2, 3])) # [2, 3, 4]\n",
      " |  \n",
      " |  pick(self, keys: 'Union[str, List[str]]') -> 'RunnableSerializable[Any, Any]'\n",
      " |      Pick keys from the dict output of this runnable.\n",
      " |      \n",
      " |      Pick single key:\n",
      " |          .. code-block:: python\n",
      " |      \n",
      " |              import json\n",
      " |      \n",
      " |              from langchain_core.runnables import RunnableLambda, RunnableMap\n",
      " |      \n",
      " |              as_str = RunnableLambda(str)\n",
      " |              as_json = RunnableLambda(json.loads)\n",
      " |              chain = RunnableMap(str=as_str, json=as_json)\n",
      " |      \n",
      " |              chain.invoke(\"[1, 2, 3]\")\n",
      " |              # -> {\"str\": \"[1, 2, 3]\", \"json\": [1, 2, 3]}\n",
      " |      \n",
      " |              json_only_chain = chain.pick(\"json\")\n",
      " |              json_only_chain.invoke(\"[1, 2, 3]\")\n",
      " |              # -> [1, 2, 3]\n",
      " |      \n",
      " |      Pick list of keys:\n",
      " |          .. code-block:: python\n",
      " |      \n",
      " |              from typing import Any\n",
      " |      \n",
      " |              import json\n",
      " |      \n",
      " |              from langchain_core.runnables import RunnableLambda, RunnableMap\n",
      " |      \n",
      " |              as_str = RunnableLambda(str)\n",
      " |              as_json = RunnableLambda(json.loads)\n",
      " |              def as_bytes(x: Any) -> bytes:\n",
      " |                  return bytes(x, \"utf-8\")\n",
      " |      \n",
      " |              chain = RunnableMap(\n",
      " |                  str=as_str,\n",
      " |                  json=as_json,\n",
      " |                  bytes=RunnableLambda(as_bytes)\n",
      " |              )\n",
      " |      \n",
      " |              chain.invoke(\"[1, 2, 3]\")\n",
      " |              # -> {\"str\": \"[1, 2, 3]\", \"json\": [1, 2, 3], \"bytes\": b\"[1, 2, 3]\"}\n",
      " |      \n",
      " |              json_and_bytes_chain = chain.pick([\"json\", \"bytes\"])\n",
      " |              json_and_bytes_chain.invoke(\"[1, 2, 3]\")\n",
      " |              # -> {\"json\": [1, 2, 3], \"bytes\": b\"[1, 2, 3]\"}\n",
      " |  \n",
      " |  pipe(self, *others: 'Union[Runnable[Any, Other], Callable[[Any], Other]]', name: 'Optional[str]' = None) -> 'RunnableSerializable[Input, Other]'\n",
      " |      Compose this Runnable with Runnable-like objects to make a RunnableSequence.\n",
      " |      \n",
      " |      Equivalent to `RunnableSequence(self, *others)` or `self | others[0] | ...`\n",
      " |      \n",
      " |      Example:\n",
      " |          .. code-block:: python\n",
      " |      \n",
      " |              from langchain_core.runnables import RunnableLambda\n",
      " |      \n",
      " |              def add_one(x: int) -> int:\n",
      " |                  return x + 1\n",
      " |      \n",
      " |              def mul_two(x: int) -> int:\n",
      " |                  return x * 2\n",
      " |      \n",
      " |              runnable_1 = RunnableLambda(add_one)\n",
      " |              runnable_2 = RunnableLambda(mul_two)\n",
      " |              sequence = runnable_1.pipe(runnable_2)\n",
      " |              # Or equivalently:\n",
      " |              # sequence = runnable_1 | runnable_2\n",
      " |              # sequence = RunnableSequence(first=runnable_1, last=runnable_2)\n",
      " |              sequence.invoke(1)\n",
      " |              await sequence.ainvoke(1)\n",
      " |              # -> 4\n",
      " |      \n",
      " |              sequence.batch([1, 2, 3])\n",
      " |              await sequence.abatch([1, 2, 3])\n",
      " |              # -> [4, 6, 8]\n",
      " |  \n",
      " |  transform(self, input: 'Iterator[Input]', config: 'Optional[RunnableConfig]' = None, **kwargs: 'Optional[Any]') -> 'Iterator[Output]'\n",
      " |      Default implementation of transform, which buffers input and then calls stream.\n",
      " |      Subclasses should override this method if they can start producing output while\n",
      " |      input is still being generated.\n",
      " |  \n",
      " |  with_config(self, config: 'Optional[RunnableConfig]' = None, **kwargs: 'Any') -> 'Runnable[Input, Output]'\n",
      " |      Bind config to a Runnable, returning a new Runnable.\n",
      " |  \n",
      " |  with_fallbacks(self, fallbacks: 'Sequence[Runnable[Input, Output]]', *, exceptions_to_handle: 'Tuple[Type[BaseException], ...]' = (<class 'Exception'>,), exception_key: 'Optional[str]' = None) -> 'RunnableWithFallbacksT[Input, Output]'\n",
      " |      Add fallbacks to a runnable, returning a new Runnable.\n",
      " |      \n",
      " |      Example:\n",
      " |      \n",
      " |          .. code-block:: python\n",
      " |      \n",
      " |              from typing import Iterator\n",
      " |      \n",
      " |              from langchain_core.runnables import RunnableGenerator\n",
      " |      \n",
      " |      \n",
      " |              def _generate_immediate_error(input: Iterator) -> Iterator[str]:\n",
      " |                  raise ValueError()\n",
      " |                  yield \"\"\n",
      " |      \n",
      " |      \n",
      " |              def _generate(input: Iterator) -> Iterator[str]:\n",
      " |                  yield from \"foo bar\"\n",
      " |      \n",
      " |      \n",
      " |              runnable = RunnableGenerator(_generate_immediate_error).with_fallbacks(\n",
      " |                  [RunnableGenerator(_generate)]\n",
      " |                  )\n",
      " |              print(''.join(runnable.stream({}))) #foo bar\n",
      " |      \n",
      " |      Args:\n",
      " |          fallbacks: A sequence of runnables to try if the original runnable fails.\n",
      " |          exceptions_to_handle: A tuple of exception types to handle.\n",
      " |          exception_key: If string is specified then handled exceptions will be passed\n",
      " |              to fallbacks as part of the input under the specified key. If None,\n",
      " |              exceptions will not be passed to fallbacks. If used, the base runnable\n",
      " |              and its fallbacks must accept a dictionary as input.\n",
      " |      \n",
      " |      Returns:\n",
      " |          A new Runnable that will try the original runnable, and then each\n",
      " |          fallback in order, upon failures.\n",
      " |  \n",
      " |  with_listeners(self, *, on_start: 'Optional[Listener]' = None, on_end: 'Optional[Listener]' = None, on_error: 'Optional[Listener]' = None) -> 'Runnable[Input, Output]'\n",
      " |      Bind lifecycle listeners to a Runnable, returning a new Runnable.\n",
      " |      \n",
      " |      on_start: Called before the runnable starts running, with the Run object.\n",
      " |      on_end: Called after the runnable finishes running, with the Run object.\n",
      " |      on_error: Called if the runnable throws an error, with the Run object.\n",
      " |      \n",
      " |      The Run object contains information about the run, including its id,\n",
      " |      type, input, output, error, start_time, end_time, and any tags or metadata\n",
      " |      added to the run.\n",
      " |      \n",
      " |      Example:\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |          from langchain_core.runnables import RunnableLambda\n",
      " |          import time\n",
      " |      \n",
      " |          def test_runnable(time_to_sleep : int):\n",
      " |              time.sleep(time_to_sleep)\n",
      " |      \n",
      " |          def fn_start(run_obj : Runnable):\n",
      " |              print(\"start_time:\", run_obj.start_time)\n",
      " |      \n",
      " |          def fn_end(run_obj : Runnable):\n",
      " |              print(\"end_time:\", run_obj.end_time)\n",
      " |      \n",
      " |          RunnableLambda(test_runnable).with_listeners(\n",
      " |              on_start=fn_start,\n",
      " |              on_end=fn_end\n",
      " |              ).invoke(2)\n",
      " |  \n",
      " |  with_retry(self, *, retry_if_exception_type: 'Tuple[Type[BaseException], ...]' = (<class 'Exception'>,), wait_exponential_jitter: 'bool' = True, stop_after_attempt: 'int' = 3) -> 'Runnable[Input, Output]'\n",
      " |      Create a new Runnable that retries the original runnable on exceptions.\n",
      " |      \n",
      " |      Example:\n",
      " |      \n",
      " |      .. code-block:: python\n",
      " |          from langchain_core.runnables import RunnableLambda\n",
      " |      \n",
      " |          count = 0\n",
      " |      \n",
      " |      \n",
      " |          def _lambda(x: int) -> None:\n",
      " |              global count\n",
      " |              count = count + 1\n",
      " |              if x == 1:\n",
      " |                  raise ValueError(\"x is 1\")\n",
      " |              else:\n",
      " |                   pass\n",
      " |      \n",
      " |      \n",
      " |          runnable = RunnableLambda(_lambda)\n",
      " |          try:\n",
      " |              runnable.with_retry(\n",
      " |                  stop_after_attempt=2,\n",
      " |                  retry_if_exception_type=(ValueError,),\n",
      " |              ).invoke(1)\n",
      " |          except ValueError:\n",
      " |              pass\n",
      " |      \n",
      " |          assert (count == 2)\n",
      " |      \n",
      " |      \n",
      " |      Args:\n",
      " |          retry_if_exception_type: A tuple of exception types to retry on\n",
      " |          wait_exponential_jitter: Whether to add jitter to the wait time\n",
      " |                                   between retries\n",
      " |          stop_after_attempt: The maximum number of attempts to make before giving up\n",
      " |      \n",
      " |      Returns:\n",
      " |          A new Runnable that retries the original runnable on exceptions.\n",
      " |  \n",
      " |  with_types(self, *, input_type: 'Optional[Type[Input]]' = None, output_type: 'Optional[Type[Output]]' = None) -> 'Runnable[Input, Output]'\n",
      " |      Bind input and output types to a Runnable, returning a new Runnable.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Readonly properties inherited from langchain_core.runnables.base.Runnable:\n",
      " |  \n",
      " |  config_specs\n",
      " |      List configurable fields for this runnable.\n",
      " |  \n",
      " |  input_schema\n",
      " |      The type of input this runnable accepts specified as a pydantic model.\n",
      " |  \n",
      " |  output_schema\n",
      " |      The type of output this runnable produces specified as a pydantic model.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data and other attributes inherited from langchain_core.runnables.base.Runnable:\n",
      " |  \n",
      " |  name = None\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Class methods inherited from typing.Generic:\n",
      " |  \n",
      " |  __class_getitem__(params) from pydantic.v1.main.ModelMetaclass\n",
      " |  \n",
      " |  __init_subclass__(*args, **kwargs) from pydantic.v1.main.ModelMetaclass\n",
      " |      This method is called when a class is subclassed.\n",
      " |      \n",
      " |      The default implementation does nothing. It may be\n",
      " |      overridden to extend subclasses.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(Tongyi)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## RAG应用实现\n",
    "\n",
    "https://blog.csdn.net/itnerd/article/details/137522411\n",
    "\n",
    "https://blog.csdn.net/csdn_xmj/article/details/136592846\n",
    "\n",
    "https://github.com/langchain-ai/streamlit-agent/blob/main/streamlit_agent/chat_with_documents.py\n",
    "\n",
    "https://docs.streamlit.io/develop/api-reference/widgets/st.file_uploader\n",
    "\n",
    "* 原始实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[INFO] [05-14 09:12:48] openapi_requestor.py:316 [t:14188]: requesting llm api endpoint: /embeddings/embedding-v1\n",
      "[INFO] [05-14 09:12:48] oauth.py:207 [t:14188]: trying to refresh access_token for ak `og6mWr***`\n",
      "[INFO] [05-14 09:12:48] oauth.py:220 [t:14188]: sucessfully refresh access_token\n"
     ]
    }
   ],
   "source": [
    "from langchain.document_loaders import TextLoader\n",
    "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
    "from langchain_community.embeddings import QianfanEmbeddingsEndpoint\n",
    "from langchain.vectorstores import Chroma\n",
    "from langchain.chains.combine_documents import create_stuff_documents_chain\n",
    "from langchain.chains import create_retrieval_chain\n",
    "from langchain.memory import ConversationBufferMemory, ConversationSummaryMemory\n",
    "from langchain.chains import ConversationalRetrievalChain\n",
    "\n",
    "model_qf = QianfanLLMEndpoint(temperature=0.1)\n",
    "loader_txt = TextLoader(r'G:\\云岚宗.txt', encoding='utf8')\n",
    "docs_txt = loader_txt.load()\n",
    "text_splitter_txt = RecursiveCharacterTextSplitter(chunk_size = 384, chunk_overlap = 0, separators=[\"\\n\\n\", \"\\n\", \" \", \"\", \"。\", \"，\"])\n",
    "documents_txt = text_splitter_txt.split_documents(docs_txt)\n",
    "embeddings_qf = QianfanEmbeddingsEndpoint()\n",
    "vectordb = Chroma.from_documents(documents=documents_txt, embedding=embeddings_qf)\n",
    "\n",
    "prompt = ChatPromptTemplate.from_template(\"\"\"使用下面的语料来回答本模板最末尾的问题。如果你不知道问题的答案，直接回答 \"我不知道\"，禁止随意编造答案。\n",
    "        为了保证答案尽可能简洁，你的回答必须不超过三句话，你的回答中不可以带有星号。\n",
    "        请注意！在每次回答结束之后，你都必须接上 \"感谢你的提问\" 作为结束语\n",
    "        以下是一对问题和答案的样例：\n",
    "            请问：秦始皇的原名是什么\n",
    "            秦始皇原名嬴政。感谢你的提问。\n",
    "        \n",
    "        以下是语料：\n",
    "<context>\n",
    "{context}\n",
    "</context>\n",
    "\n",
    "Question: {input}\"\"\")\n",
    "#创建检索链\n",
    "\n",
    "retriever = vectordb.as_retriever()\n",
    "memory = ConversationSummaryMemory(\n",
    "    llm=model_qf, memory_key=\"chat_history\", return_messages=True\n",
    ")\n",
    "qa = ConversationalRetrievalChain.from_llm(llm=model_qf, retriever=retriever, memory=memory)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "memory.chat_memory.messages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] [05-14 09:13:00] base.py:495 [t:14188]: This key `stop` does not seem to be a parameter that the model `ERNIE-Bot-turbo` will accept\n",
      "[INFO] [05-14 09:13:00] openapi_requestor.py:316 [t:14188]: requesting llm api endpoint: /chat/eb-instant\n",
      "[INFO] [05-14 09:13:01] openapi_requestor.py:316 [t:14188]: requesting llm api endpoint: /embeddings/embedding-v1\n",
      "[WARNING] [05-14 09:13:01] base.py:495 [t:14188]: This key `stop` does not seem to be a parameter that the model `ERNIE-Bot-turbo` will accept\n",
      "[INFO] [05-14 09:13:01] openapi_requestor.py:316 [t:14188]: requesting llm api endpoint: /chat/eb-instant\n",
      "[WARNING] [05-14 09:13:03] base.py:495 [t:14188]: This key `stop` does not seem to be a parameter that the model `ERNIE-Bot-turbo` will accept\n",
      "[INFO] [05-14 09:13:03] openapi_requestor.py:316 [t:14188]: requesting llm api endpoint: /chat/eb-instant\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "From the context, Xiao Yan is a main character who is mentioned to be a young man who is about to be married to the daughter of the Lion Heart General of the Kingdom of Jade. He is also mentioned to have a mysterious background and is described as having a strong personality and a strong sense of justice. Therefore, based on the context, Xiao Yan can be described as a young man who is about to be married to a princess, has a mysterious background, and is known for his strong personality and sense of justice.\n"
     ]
    }
   ],
   "source": [
    "res = qa.invoke(\n",
    "    {\"question\": \"萧炎是谁\"}\n",
    ")\n",
    "print(res[\"answer\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] [05-13 21:56:01] base.py:495 [t:16232]: This key `stop` does not seem to be a parameter that the model `ERNIE-Bot-turbo` will accept\n",
      "[INFO] [05-13 21:56:01] openapi_requestor.py:316 [t:16232]: requesting llm api endpoint: /chat/eb-instant\n",
      "[INFO] [05-13 21:56:02] openapi_requestor.py:316 [t:16232]: requesting llm api endpoint: /embeddings/embedding-v1\n",
      "[WARNING] [05-13 21:56:02] base.py:495 [t:16232]: This key `stop` does not seem to be a parameter that the model `ERNIE-Bot-turbo` will accept\n",
      "[INFO] [05-13 21:56:02] openapi_requestor.py:316 [t:16232]: requesting llm api endpoint: /chat/eb-instant\n",
      "[WARNING] [05-13 21:56:05] base.py:495 [t:16232]: This key `stop` does not seem to be a parameter that the model `ERNIE-Bot-turbo` will accept\n",
      "[INFO] [05-13 21:56:05] openapi_requestor.py:316 [t:16232]: requesting llm api endpoint: /chat/eb-instant\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "根据原文信息可知，萧炎并没有结婚。文中提到纳兰嫣然对萧炎哥哥与她的婚事最不满意，所以纳兰嫣然此次来解除婚约。因此，可以得出结论，萧炎目前并没有结婚。\n"
     ]
    }
   ],
   "source": [
    "res = qa.invoke(\n",
    "    {\"question\": \"他结婚了吗？\"}\n",
    ")\n",
    "print(res[\"answer\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "#help(QianfanEmbeddingsEndpoint)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* streamlit 的实现 （文件读取问题）\n",
    "\n",
    "由于和streamlit的文件读取组件不兼容，因此需要通过streamlit读取文件，然后再写入本地，然后再用langchain读取一遍"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def write_text_file(content, file_path):\n",
    "    try:\n",
    "        with open(file_path, 'w') as file:\n",
    "            file.write(content)\n",
    "        return True\n",
    "    except Exception as e:\n",
    "        print(f\"Error occurred while writing the file: {e}\")\n",
    "        return False\n",
    "\n",
    "uploaded_file = st.file_uploader(\"Upload an article\", type=\"txt\")\n",
    "if uploaded_file is not None:\n",
    "    content = uploaded_file.read().decode('utf-8')\n",
    "    # st.write(content)\n",
    "    file_path = \"file.txt\"\n",
    "    write_text_file(content, file_path)   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 基于pyinstaller的streamlit应用打包\n",
    "\n",
    "https://blog.csdn.net/Helloorld_1/article/details/131767478\n",
    "\n",
    "https://blog.csdn.net/Helloorld_1/article/details/132880784\n",
    "\n",
    "https://blog.csdn.net/nexttoparadise/article/details/135368387"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
